package com.select.course.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.select.course.entity.*;
import com.select.course.listener.TeacherListener;
import com.select.course.mapper.UserTeacherMapper;
import com.select.course.service.*;
import com.select.course.utils.JwtUtil;
import com.select.course.utils.MsgConstant;
import com.select.course.utils.PageUtils;
import com.select.course.utils.R;
import com.select.course.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 24820
 * @description 针对表【c_user_teacher】的数据库操作Service实现
 * @createDate 2022-10-26 10:17:14
 */
@Service
public class UserTeacherServiceImpl extends ServiceImpl<UserTeacherMapper, UserTeacher>
        implements UserTeacherService {

    @Resource
    private SchoolMajorService schoolMajorService;
    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SchoolCollegeService schoolCollegeService;

    @Resource
    private SchoolClassService schoolClassService;
    @Lazy
    @Resource
    private UserStudentService userStudentService;

    @Resource
    private TeacherCourseRelationService teacherCourseRelationService;
    @Lazy
    @Resource
    private SchoolCourseService schoolCourseService;
    @Resource
    private StudentCourseRelationService studentCourseRelationService;
    @Resource
    private CourseRoomService courseRoomService;
    @Resource
    private CourseRoomRelationService courseRoomRelationService;
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public UserTeacher getPackageTeacher() {
        UserTeacher userTeacher = new UserTeacher();
        return userTeacher;

    }

    @Override
    public List<SchoolMajor> getMajorByCollege(String name) {
        SchoolCollege name1 = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", name));
        List<SchoolMajor> schoolMajorList = schoolMajorService.list(new QueryWrapper<SchoolMajor>().eq("college_id", name1.getId()));

        return schoolMajorList;


    }




    @Override
    public List<SchoolClass> getClassByIdNumber(Long idNumber) {
        List<SchoolClass> schoolClassList = schoolClassService.list(new QueryWrapper<SchoolClass>().eq("major_id", idNumber));
        return schoolClassList;
    }

    @Override
    public List<SchoolMajor> getMajorByCollegeIdNumber(Long idNumber) {
        List<SchoolMajor> schoolMajorList = schoolMajorService.list(new QueryWrapper<SchoolMajor>().eq("college_id", idNumber));
        return schoolMajorList;
    }

    @Override
    public TeacherVo getTeacherByIdNumber(String idNumber) {
        UserTeacher userTeacher = this.getOne(new QueryWrapper<UserTeacher>().eq("id_number", idNumber));
        Map<String, String> stringStringMap = userStudentService.packageCollegeAndMajor(userTeacher.getCollegeId(), null, null);
        TeacherVo teacherVo = new TeacherVo();
        BeanUtils.copyProperties(userTeacher, teacherVo);
        teacherVo.setPassword(null);
        teacherVo.setUserId(userTeacher.getIdNumber());
        teacherVo.setTeacherName(userTeacher.getTeacherName());
        teacherVo.setCollege(stringStringMap.get("collegeName"));
        return teacherVo;
    }





    @Override
    public PageUtils getTeaList(PageVo pageVo) {
        Page<UserTeacher> objectPage = new Page<UserTeacher>(pageVo.getPageNum(), pageVo.getPageSize());
        String collegeName = pageVo.getCollege();
        QueryWrapper<UserTeacher> userTeacherQueryWrapper = new QueryWrapper<>();

        if (!StringUtils.isEmpty(collegeName)) {
            SchoolCollege college = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", collegeName));
            userTeacherQueryWrapper.eq("college_id",college.getId());
        }
        String select_major = pageVo.getMajor();
        if (!StringUtils.isEmpty(select_major)) {
            SchoolMajor major = schoolMajorService.getOne(new QueryWrapper<SchoolMajor>().eq("name", select_major));
            userTeacherQueryWrapper.eq("major_id",major.getId());
        }
        String sex = pageVo.getSex();
        if(!StringUtils.isEmpty(sex)) {
            userTeacherQueryWrapper.eq("sex", sex);
        }
        String queryInfo = pageVo.getQuery();
        if (!StringUtils.isEmpty(queryInfo)) {
            userTeacherQueryWrapper.and(wrapper -> {
                wrapper.like("teacher_name", queryInfo).or().like("id_number", queryInfo);
            });
        }
        Page<UserTeacher> page = this.page(objectPage, userTeacherQueryWrapper);
        List<UserTeacher> records = page.getRecords();
        List<TeacherVo> collect = records.stream().map(e -> {
            TeacherVo teacherVo = new TeacherVo();
            teacherVo.setTeacherName(e.getTeacherName());
            teacherVo.setUserId(e.getIdNumber());
            teacherVo.setId(e.getId());
            teacherVo.setAge(e.getAge());
            teacherVo.setSex(e.getSex());
            teacherVo.setRegisterTime(e.getRegisterTime());
            SchoolCollege college_id = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("id", e.getCollegeId()));
            teacherVo.setCollege(college_id.getName());
            return teacherVo;
        }).collect(Collectors.toList());
        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(collect);
        return pageUtils;

    }

    @Override
    public R addTeacher(TeacherVo teacherVo) {
        UserTeacher userTeacher = new UserTeacher();
        long idNumber = this.count(new QueryWrapper<UserTeacher>().eq("id_number", teacherVo.getUserId()));
        long idNumber2 = userStudentService.count(new QueryWrapper<UserStudent>().eq("id_number", teacherVo.getUserId()));

        if (idNumber > 0 || idNumber2 > 0) {
            return R.error(MsgConstant.UserEnum.USER_DUPLICATE.getCode(), MsgConstant.UserEnum.USER_DUPLICATE.getMsg());
        } else {
            BeanUtils.copyProperties(teacherVo, userTeacher);
            userTeacher.setIdNumber(teacherVo.getUserId());
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            String encode = bCryptPasswordEncoder.encode(teacherVo.getUserId());
            userTeacher.setPassword(encode);
            userTeacher.setTeacherName(teacherVo.getTeacherName());
            userTeacher.setRegisterTime(new Date());
            SchoolCollege schoolCollege = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", teacherVo.getCollege()));
            userTeacher.setCollegeId(schoolCollege.getId());
            try {
                this.save(userTeacher);
            } catch (Exception e) {
                return R.error(MsgConstant.UserEnum.USER_DUPLICATE.getCode(), MsgConstant.UserEnum.USER_DUPLICATE.getMsg());
            }
            sysUserRoleService.save(new SysUserRole(userTeacher.getIdNumber(), "2"));
            return R.ok();
        }

    }

    @Transactional
    @Override
    public R deleteTeacher(Long userId) {
        List<TeacherCourseRelation> teacherCourseRelations = teacherCourseRelationService.list(new QueryWrapper<TeacherCourseRelation>().eq("teacher_id", userId));
        teacherCourseRelations.forEach(e -> {
            //删除课程
            schoolCourseService.removeById(e.getCourseId());
            //删除教室
            courseRoomRelationService.remove(new QueryWrapper<CourseRoomRelation>().eq("course_id", e.getCourseId()));
            //删除选课数据
            studentCourseRelationService.remove(new QueryWrapper<StudentCourseRelation>().eq("course_id", e.getCourseId()));
        });
        teacherCourseRelationService.remove(new QueryWrapper<TeacherCourseRelation>().eq("teacher_id", userId));
        boolean id = this.remove(new QueryWrapper<UserTeacher>().eq("id_number", userId));
        if (id) {
            return R.ok();
        }
        return R.error(MsgConstant.UserEnum.USER_DELETE_FAIL.getCode(), MsgConstant.UserEnum.USER_DELETE_FAIL.getMsg());
    }

    @Override
    public R updateTeacher(TeacherVo teacherVo) {
        UserTeacher userTeacher = new UserTeacher();
        userTeacher.setTeacherName(teacherVo.getTeacherName());
        userTeacher.setSex(teacherVo.getSex());
        userTeacher.setAge(teacherVo.getAge());
        userTeacher.setEmail(teacherVo.getEmail());
        if (teacherVo.getPassword() != null) {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            String encode = bCryptPasswordEncoder.encode(teacherVo.getPassword());
            userTeacher.setPassword(encode);
        }
//        SchoolCollege name = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", teacherVo.getCollege()));
//        userTeacher.setCollegeId(name.getId());
        boolean idNumber = this.update(userTeacher, new QueryWrapper<UserTeacher>().eq("id_number", teacherVo.getUserId()));
        if (idNumber) {
            return R.ok();
        }
        return R.error(MsgConstant.UserEnum.USER_UPDATE_FAIL.getCode(), MsgConstant.UserEnum.USER_UPDATE_FAIL.getMsg());
    }

    @Override
    public R updateSelf(TeacherVo teacherVo) {
//        UserStudent userStudent = this.packageStudent(studentVo);
//        this.update(userStudent, new QueryWrapper<UserStudent>().eq("id_number", userStudent.getIdNumber()));
//
//        Map<String, Long> stringLongMap = userStudentService.releaseCollegeAndMajor(teacherVo.getCollege(), null, null);
//        UserTeacher userTeacher = new UserTeacher();
//        BeanUtils.copyProperties(teacherVo,userTeacher);
//        userTeacher.setIdNumber(teacherVo.getUserId());
//        userTeacher.setCollegeId(stringLongMap.get("collegeId"));
//        this.update(userTeacher,new QueryWrapper<UserTeacher>().eq("id_number",userTeacher.getIdNumber()));
        R r = this.updateTeacher(teacherVo);
        return r;
    }

    @Override
    public R loginTeacher(TeacherVo teacherVo) {
//        UserTeacher id_number = this.getOne(new QueryWrapper<UserTeacher>().eq("id_number", teacherVo.getUserId()));
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(teacherVo.getUserId(), teacherVo.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("登陆失败！");
        }
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        if (!loginUser.getPermissions().get(0).toString().equals("ROLE_teacher")) {
            throw new RuntimeException("账号错误！");
        }
        String jwt = JwtUtil.createJWT(loginUser.getUser().getIdNumber());
        Map<String, Object> map = new HashMap<>();
        map.put("authentication", jwt);
        map.put("username", loginUser.getUser().getUserName());
        return R.ok(map);

    }

    @Override
    public PageUtils getCurriList(CoursePageVo coursePageVo) {
        String userId = coursePageVo.getUserId();
        if (userId == null) {
            return null;
        }
        Page<SchoolCourse> schoolCoursePage = new Page<>(coursePageVo.getPageNum(), coursePageVo.getPageSize());
        QueryWrapper<SchoolCourse> wrapper = new QueryWrapper<>();
        UserTeacher userTeacher = this.getOne(new QueryWrapper<UserTeacher>().eq("id_number", userId));
        List<TeacherCourseRelation> teacherCourseRelations = teacherCourseRelationService.list(new QueryWrapper<TeacherCourseRelation>().eq("teacher_id", userTeacher.getId()));
        if (!StringUtils.isEmpty(teacherCourseRelations)) {
            List<Long> courseIds = teacherCourseRelations.stream().map(e -> {
                Long courseId = e.getCourseId();
                return courseId;
            }).collect(Collectors.toList());
            wrapper.in("id",courseIds);
        }

        Integer courseCore = coursePageVo.getCourseCore();
        if (!StringUtils.isEmpty(courseCore)) {
            wrapper.eq("course_core",courseCore);
        }
        String courseType = coursePageVo.getCourseType();
        if (!StringUtils.isEmpty(courseType)) {
            if (courseType.equals("必修")) {
                wrapper.eq("course_type",1);
            }else {
                wrapper.eq("course_type",0);
            }
        }
        String query = coursePageVo.getQuery();
        if (!StringUtils.isEmpty(query)) {
            wrapper.and(e1 -> {
                e1.like("name", query).or().like("course_id", query);
            });
        }
        Page<SchoolCourse> page = schoolCourseService.page(schoolCoursePage, wrapper);
        List<SchoolCourse> records = page.getRecords();
        List<CourseVo> collect = records.stream().map(e -> {
            CourseVo courseVo = new CourseVo();
            BeanUtils.copyProperties(e,courseVo);
            CourseVo courseVo1 = userStudentService.packageCourseVo(e, courseVo);
            return courseVo1;
        }).collect(Collectors.toList());

        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(collect);
        return pageUtils;

    }

    @Override
    public PageUtils getSelection(CoursePageVo coursePageVo) {
        PageUtils curriList = this.getCurriList(coursePageVo);
        List<CourseVo> list = (List<CourseVo>) curriList.getList();
        List<CourseVo> courseVoList = list.stream().map(e -> {
            SchoolCourse schoolCourse = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("course_id", e.getCourseId()));
            long count = studentCourseRelationService.count(new QueryWrapper<StudentCourseRelation>().eq("course_id", schoolCourse.getId()));
            e.setCourseCount(count);
            e.setId(schoolCourse.getId());
            return e;
        }).collect(Collectors.toList());
        curriList.setList(courseVoList);
        return curriList;
    }



    @Override
    public R getCurri(Long id) {
        SchoolCourse byId = schoolCourseService.getById(id);
        CourseVo courseVo = new CourseVo();
        CourseVo packageCourseVo = userStudentService.packageCourseVo(byId, courseVo);
        if (!StringUtils.isEmpty(packageCourseVo)) {
            return R.ok().put("data",packageCourseVo);
        }

        return R.error(101,"获取当前课程信息失败，请联系管理员！");
    }

    @Override
    public R getAllSelection(Long id) {
        List<StudentCourseRelation> studentCourseRelations = studentCourseRelationService.list(new QueryWrapper<StudentCourseRelation>().eq("course_id", id));
        List<StudentVo> collect = studentCourseRelations.stream().map(e -> {
            UserStudent byId = userStudentService.getOne(new QueryWrapper<UserStudent>().eq("id_number", e.getStudentId()));
            StudentVo studentVo = userStudentService.packageStudentVo(byId);
            studentVo.setXuankeTime(e.getRegisterTime());
            return studentVo;
        }).collect(Collectors.toList());
        if (collect != null && collect.size() > 0) {
            return R.ok().put("data", collect);
        }

        return R.error(101, "获取当前选课信息失败，请联系管理员！");
    }

    @Transactional
    @Override
    public R updateCurri(CourseVo courseVo) {
        SchoolCourse schoolCourse = new SchoolCourse();
        schoolCourse.setCourseCount(courseVo.getCourseCount());
        schoolCourse.setCourseCore(courseVo.getCourseCore());
        schoolCourse.setId(courseVo.getId());
        schoolCourse.setName(courseVo.getName());
        String endWeek = courseVo.getEndWeek().substring(1, courseVo.getEndWeek().length() - 1);
        schoolCourse.setEndWeek(endWeek);
        String startWeek = courseVo.getStartWeek().substring(1, courseVo.getStartWeek().length() - 1);
        schoolCourse.setStartWeek(startWeek);
        schoolCourse.setWeekTime(courseVo.getWeekTime());
        schoolCourse.setClassTime(courseVo.getClassTime());
        schoolCourseService.updateById(schoolCourse);


        CourseRoomRelation courseRoomRelation = new CourseRoomRelation();
        CourseRoom courseRoom = courseRoomService.getOne(new QueryWrapper<CourseRoom>().eq("room_name", courseVo.getClassRoom()));
        CourseRoomRelation courseRoomRelationServiceOne = courseRoomRelationService.getOne(new QueryWrapper<CourseRoomRelation>().eq("course_id", schoolCourse.getId()));
        courseRoomRelation.setRoomId(courseRoom.getId());
        courseRoomRelation.setCourseId(courseVo.getId());
        if (!StringUtils.isEmpty(courseRoomRelationServiceOne)) {
            courseRoomRelation.setId(courseRoomRelationServiceOne.getId());
            courseRoomRelationService.updateById(courseRoomRelation);
        } else {
            courseRoomRelationService.save(courseRoomRelation);
        }

        return R.ok();

    }

    @Transactional
    @Override
    public R addClass(CourseVo courseVo) {
        SchoolCourse schoolCourse = new SchoolCourse();
        schoolCourse.setCourseId(courseVo.getCourseId());
        schoolCourse.setName(courseVo.getName());
        schoolCourse.setCourseCount(courseVo.getCourseCount());
        schoolCourse.setCourseCore(courseVo.getCourseCore());
        String endWeek = courseVo.getEndWeek().substring(1, courseVo.getEndWeek().length() - 1);
        schoolCourse.setEndWeek(endWeek);
        String startWeek = courseVo.getStartWeek().substring(1, courseVo.getStartWeek().length() - 1);
        schoolCourse.setStartWeek(startWeek);
        schoolCourse.setWeekTime(courseVo.getWeekTime());
        schoolCourse.setClassTime(courseVo.getClassTime());
        if (courseVo.getCourseType().equals("必修")) {
            schoolCourse.setCourseType(1);

        } else {
            schoolCourse.setCourseType(0);
        }
        schoolCourseService.save(schoolCourse);
        Long id = schoolCourse.getId();
        CourseRoomRelation courseRoomRelation = new CourseRoomRelation();
        CourseRoom room_name = courseRoomService.getOne(new QueryWrapper<CourseRoom>().eq("room_name", courseVo.getClassRoom()));
        courseRoomRelation.setRoomId(room_name.getId());
        courseRoomRelation.setCourseId(id);

        courseRoomRelationService.save(courseRoomRelation);
        TeacherCourseRelation teacherCourseRelation = new TeacherCourseRelation();
        UserTeacher userTeacher = this.getOne(new QueryWrapper<UserTeacher>().eq("id_number", courseVo.getUserId()));
        teacherCourseRelation.setTeacherId(userTeacher.getId());
        teacherCourseRelation.setCourseId(id);
        teacherCourseRelation.setRegisterTime(new Date());
        teacherCourseRelationService.save(teacherCourseRelation);
        return R.ok();
    }

    @Transactional
    @Override
    public R deleteCourse(Long courseId) {
        // 删除关联的教室
        boolean courseRoom = courseRoomRelationService.remove(new QueryWrapper<CourseRoomRelation>().eq("course_id", courseId));
        // 删除关联的老师
        boolean teacherCourse = teacherCourseRelationService.remove(new QueryWrapper<TeacherCourseRelation>().eq("course_id", courseId));
        //删除该课程
        boolean schoolCourse = schoolCourseService.removeById(courseId);
        boolean studentCourse = studentCourseRelationService.remove(new QueryWrapper<StudentCourseRelation>().eq("course_id", courseId));

        if (courseRoom && teacherCourse && schoolCourse && studentCourse) {
            return R.ok();
        }

        return R.error(111, "删除失败！");


    }

    @Override
    public R getSelectionNum(String userId) {
        UserTeacher idNumber = this.getOne(new QueryWrapper<UserTeacher>().eq("id_number", userId));
        List<TeacherCourseRelation> teacherCourseRelations = teacherCourseRelationService.list(new QueryWrapper<TeacherCourseRelation>().eq("teacher_id", idNumber.getId()));
        List<HashMap<String, String>> hashMap = teacherCourseRelations.stream().map(e -> {
            HashMap<String, String> stringStringHashMap = new HashMap<>();
            SchoolCourse schoolCourse = schoolCourseService.getOne(new QueryWrapper<SchoolCourse>().eq("id", e.getCourseId()));
            long courseCount = studentCourseRelationService.count(new QueryWrapper<StudentCourseRelation>().eq("course_id", e.getCourseId()));
            stringStringHashMap.put("kechengname", schoolCourse.getName());
            stringStringHashMap.put("选课人数", String.valueOf(courseCount));
            return stringStringHashMap;
        }).collect(Collectors.toList());
        return R.ok().put("data", hashMap);


    }

    @Override
    public UserTeacher releaseTeacherVo(TeacherVo dictEeVo) {
        UserTeacher userTeacher = new UserTeacher();
        BeanUtils.copyProperties(dictEeVo, userTeacher);
        userTeacher.setIdNumber(dictEeVo.getUserId());
        userTeacher.setPassword(dictEeVo.getUserId());
        SchoolCollege name = schoolCollegeService.getOne(new QueryWrapper<SchoolCollege>().eq("name", dictEeVo.getCollege()));
        if (name != null) {
            userTeacher.setCollegeId(name.getId());
        } else userTeacher.setCollegeId(999L);
        userTeacher.setRegisterTime(new Date());
        userTeacher.setAge(dictEeVo.getAge());
        return userTeacher;
    }

    @Override
    public R importData(MultipartFile file) {
        try {
            TeacherListener teacherListener = new TeacherListener(this);
            EasyExcel.read(file.getInputStream(), TeacherVo.class, teacherListener).sheet().doRead();
            return R.ok().put("successCount", teacherListener.getSuccessCount());
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }

    @Override
    public void exportData(HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            String fileName = URLEncoder.encode("教师信息表", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            List<UserTeacher> userTeacherList = baseMapper.selectList(null);
            List<TeacherVo> teacherVoList = new ArrayList<>(userTeacherList.size());
            for (UserTeacher userTeacher : userTeacherList) {
                TeacherVo userTeacherVo = this.getTeacherByIdNumber(userTeacher.getIdNumber());
                teacherVoList.add(userTeacherVo);
            }
            ArrayList<String> strings = new ArrayList<>();
            strings.add("password");
            EasyExcel.write(response.getOutputStream(), TeacherVo.class).excludeColumnFiledNames(strings).sheet("教师信息表").doWrite(teacherVoList);
        } catch (IOException e) {
            throw new RuntimeException();
        }
    }


}




